/**	@file Add.cpp */
#include "Add.h"
#include "Number.h"
#include "Sym.h"
#include "operators.h"
#include "Utilities.h"
namespace sympycpp {
Add::Add(const Add & o) : Ex(ADD) {
	sign(o.sign());
	for (const_iterator i = o.args_.begin(); i != o.args_.end(); ++i) {
		Ex * pl = (*i)->copy();//allocation of new identical object 
		args_.push_back(pl);
	}
}
Add::Add(basic_container & v, const allocationPolicy flag) : Ex(ADD) { //stealing constructor 
	v.swap(args_);
}
Add::~Add(){
	for (iterator i = args_.begin(); i != args_.end(); ++i) {
		delete (*i);
	}
}
bool Add::omit(iterator & index) {
	assert(index != args_.end());
	if (args_.size() == 2) {
		return false;
	}
	iterator rem(index); 
	args_.erase(index, ++rem);
	return true;
}
std::string Add::treeView(const int i) const {
	std::ostringstream stream;
	spaces(i, stream);
	char ch = sign() ? '+' : '-';
	stream << ">("<< ch << ")" << "ADD"<<std::endl;
	for (const_iterator j = args_.begin(); j != args_.end(); ++j) {
		stream << (*j)->treeView(i+1);
	}
	return stream.str();
}
void Add::sign(const Sign s) {
	if (s == minus) {
		for (iterator i = args_.begin(); i != args_.end(); ++i) {
			(*i)->sign(!(*i)->sign());
		}
	}
}
size_t Add::size() const {
	return args_.size();
}
std::string Add::str() const {
	if (sign()) {
		return unsigned_str();
	}
	else {
		return "-(" + unsigned_str() + ")";
	}
}
std::string Add::unsigned_str() const {
	std::string textBuffer("");
	const_iterator last = args_.end();
	--last;
	for (const_iterator i = args_.begin(); i != args_.end(); ++i) {
		if ((*i)->isNum()) { // elimination parentheses for negative Numbers  (special str --> str2)
			textBuffer += ((Number *)(*i))->str2();
		}
		else {
			textBuffer += (*i)->str();
		}
		const_iterator ii = i;
		++ii;
		if ((i != last) && (*(ii))->sign()) { 
			textBuffer += "+";
		} // minus in substracion is represented by unary minus 
	}	  // consequently minus is printed to string by its owner
	return textBuffer;
}
size_t Add::rsize(const bool all) const {
	size_t suma = 0;
	for (const_iterator i =  args_.begin(); i != args_.end(); ++i) {
		suma += (*i)->rsize(false);
	}
	return suma;
}
size_t Add::asize() const {
	return args_.size();
}

bool Add::moreThan1Multiple() const {
	bool one = false;
	for (const_iterator i = args_.begin(); i != args_.end(); ++i) {
		if ((*i)->isMultiple()) {
			if (one) {
				return true;
			}
			one = true;
		}
	}
	return false;
}
Ex * Add::copy() const {
	return new Add(*this);
}

Ex * Add::diff(const Sym & x) const {
	basic_container addends;
	for (const_iterator i = args_.begin(); i != args_.end(); ++i) {
		Ex * temp = (*i)->diff(x);
		addends.push_back(temp);
	}
	return Utilities::constructorAdd(addends, STEALING);
}
}
